package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Autowired
	VodService vodService;

	@Autowired
	private TrackStatMapper trackStatMapper;

	@Autowired
	AlbumInfoMapper albumInfoMapper;

	@Autowired
	VodConstantProperties vodConstantProperties;

	@Override
	public void saveTrackInfo(TrackInfoVo trackInfoVo) {
		Long userId = AuthContextHolder.getUserId();
		TrackInfo trackInfo = new TrackInfo();
		BeanUtils.copyProperties(trackInfoVo,trackInfo);
		trackInfo.setUserId(userId);

		TrackMediaInfoVo trackMediaInfoVo = vodService.getMedTrackInfo(trackInfoVo.getMediaFileId());
		if(trackMediaInfoVo !=null){
			trackInfo.setMediaDuration(new BigDecimal(trackMediaInfoVo.getDuration().toString()));
			trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
			trackInfo.setMediaType(trackMediaInfoVo.getType());
			trackInfo.setMediaSize(trackMediaInfoVo.getSize());
		}

		LambdaQueryWrapper<TrackInfo>wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(TrackInfo::getAlbumId,trackInfoVo.getAlbumId());
		wrapper.orderByDesc(TrackInfo::getOrderNum);
		wrapper.last("limit 1");
		TrackInfo trackInfo1 = trackInfoMapper.selectOne(wrapper);
		Integer orderNum = trackInfo1 == null ? 1 : trackInfo1.getOrderNum() + 1;
		trackInfo.setOrderNum(orderNum);
		int insert = trackInfoMapper.insert(trackInfo);
		System.out.println(insert+"报存结构");
		// 2.保存声音的统计表
		saveTrackStat(trackInfo.getId()); // 3.反向修改该专辑对应的声音级数
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		if (albumInfo != null){
			albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
		}
		int insert1 = albumInfoMapper.insert(albumInfo);
		if (insert1 <=0){
			throw new GuiguException(201,"修改失败");
		}
	}


	private void saveTrackStat(Long id) {
		ArrayList<String> trackStatTypeList = new ArrayList<>();
		trackStatTypeList.add(SystemConstant.TRACK_STAT_PLAY);
		trackStatTypeList.add(SystemConstant.TRACK_STAT_COLLECT);
		trackStatTypeList.add(SystemConstant.TRACK_STAT_PRAISE);
		trackStatTypeList.add(SystemConstant.TRACK_STAT_COMMENT);
		for (String typeName : trackStatTypeList) {
			TrackStat trackStat = new TrackStat();
			trackStat.setTrackId(id);
			trackStat.setStatType(typeName);
			trackStat.setStatNum(0);
			int insert = trackStatMapper.insert(trackStat);
			if (insert <= 0) {
				log.info("保存声音统计失败");
				throw new GuiguException(201, "保存声音统计失败");
			}
			log.info("保存声音统计成功");
		}
	}

	@Override
	public IPage<TrackListVo> findUserTrackPage(IPage<TrackListVo> page, TrackInfoQuery trackInfoQuery) {
		return trackInfoMapper.findUserTrackPage(page, trackInfoQuery);
	}

	@Transactional
	@Override
	public void removeTrackInfo(Long trackId) {
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		// 1.删除声音的基本信息
		if (!this.removeById(trackId)) {
			throw new GuiguException(201, "删除声音失败");
		}
		// 3.删除vod中上传的声音（临时目录下的声音文件也不需要）
		if (trackInfo != null) {
			removeVodMediaByFileId(trackInfo.getMediaFileId());
			// 4.反向修改专辑中的包含声音级数的数量
			AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
			if (albumInfo != null) {
				albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
				albumInfoMapper.updateById(albumInfo);
			}
		}
	}

	@Override
	public TrackInfo getTrackInfo(Long trackId) {
		return trackInfoMapper.selectById(trackId);
	}

	@Override
	public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		// 获取老声音的文件id
		String oldMediaFileId = trackInfo.getMediaFileId();
		if (trackInfo == null) {
			throw new GuiguException(201, "声音不存在");
		}
		BeanUtils.copyProperties(trackInfoVo, trackInfo);
		trackInfo.setUserId(AuthContextHolder.getUserId());
		if (!StringUtils.isEmpty(trackInfoVo.getMediaFileId()) && !oldMediaFileId.equals(trackInfoVo.getMediaFileId())) {
			TrackMediaInfoVo mediaInfo = getMediaInfo(trackInfoVo.getMediaFileId());
			trackInfo.setMediaSize(mediaInfo.getSize());
			trackInfo.setMediaDuration(new BigDecimal(mediaInfo.getDuration()));
			trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
			trackInfo.setMediaType(mediaInfo.getType());
		}
		// 如果不满足if 代表没有修改过新的声音 否则 代表修改过
		trackInfoMapper.updateById(trackInfo);
	}

	private TrackMediaInfoVo getMediaInfo(String mediaFileId) {
		try {
			// 1.获取一个Credential的实例对象
			Credential cred = new Credential(vodConstantProperties.getSecretId(), vodConstantProperties.getSecretKey());
			// 2.实例化要请求产品的client对象
			VodClient client = new VodClient(cred, vodConstantProperties.getRegion());
			// 3.实例化一个请求对象,每个接口都会对应一个request对象
			DescribeMediaInfosRequest req = new DescribeMediaInfosRequest();
			// 4.封装请求参数
			String[] fileIds1 = new String[]{mediaFileId};
			// 5.把请求参数放到请求对象中
			req.setFileIds(fileIds1);
			// 6.得到响应
			DescribeMediaInfosResponse resp = client.DescribeMediaInfos(req);
			// 输出json格式的字符串回包
			System.out.println(AbstractModel.toJsonString(resp));

			// 7.解析数据
			MediaInfo[] mediaInfoSet = resp.getMediaInfoSet();
			if (mediaInfoSet != null && mediaInfoSet.length > 0) {
				MediaInfo mediaInfo = mediaInfoSet[0];
				TrackMediaInfoVo trackMediaInfoVo = new TrackMediaInfoVo();
				trackMediaInfoVo.setSize(mediaInfo.getMetaData().getSize());
				trackMediaInfoVo.setDuration(mediaInfo.getMetaData().getDuration());
				trackMediaInfoVo.setMediaUrl(mediaInfo.getBasicInfo().getMediaUrl());
				trackMediaInfoVo.setType(mediaInfo.getBasicInfo().getType());
				return trackMediaInfoVo;
			}


		} catch (Exception e) {
			System.out.println(e.toString());
		}
		throw new GuiguException(201, "获取媒体资源失败");

	}

	//删除vod中的声音
	private void removeVodMediaByFileId(String mediaFileId) {
		try {
			Credential cred = new Credential(vodConstantProperties.getSecretId(), vodConstantProperties.getSecretKey());

			// 实例化要请求产品的client对象,clientProfile是可选的
			VodClient client = new VodClient(cred, vodConstantProperties.getRegion());
			// 实例化一个请求对象,每个接口都会对应一个request对象
			DeleteMediaRequest req = new DeleteMediaRequest();
			req.setFileId(mediaFileId);

			// 返回的resp是一个DeleteMediaResponse的实例，与请求对象对应
			DeleteMediaResponse resp = client.DeleteMedia(req);
			// 输出json格式的字符串回包
			System.out.println(AbstractModel.toJsonString(resp));
		} catch (Exception ex) {
			log.error("删除vod中的文件失败", ex.getMessage());
			throw new GuiguException(201, "删除vod中的文件失败");
		}
	}
}
